﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using BCCommon;
using BCCommon.Enums;
using BCDto.Common.Logon;
using BCDto.Sim.Admin.Admin;
using BCDto.Sim.Admin.AdminAuth;
using BCDto.Sim.Admin.StaffOrganizationMappingRecord;
using BCDto.Sim.Company.Department;
using BCService.Sim.Admin.Admin;
using BCService.Sim.Admin.AdminAuth;
using BCService.Sim.Company.Department;
using BCService.WeChatComponent.WeChatLoginService;
using BCTMSRESTful.Configs;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace BCTMSRESTful.Controllers.Management.Admin.Admin
{
    /// <summary>
    /// 员工信息控制器
    /// </summary>
    [ApiExplorerSettings(GroupName = "Admin")]
    [Route("api/v1/sim/[controller]")]
    public class AdminsController : ManagementBaseController
    {
        private readonly IAdminService adminService;
        private readonly IAdminAuthService adminAuthService;
        private readonly IWeChatLoginService weChatLoginService;
        private readonly TimeSpan expiration = TimeSpan.FromDays(7);
        /// <summary>
        /// 员工信息控制器
        /// </summary>
        public AdminsController(IAdminService adminService, IAdminAuthService adminAuthService, IWeChatLoginService weChatLoginService)
        {
            this.adminService = adminService;
            this.adminAuthService = adminAuthService;
            this.weChatLoginService = weChatLoginService;
        }

        #region 检查登录名是否已存在
        /// <summary>
        /// 获取公司负责人配置员工列表。
        /// </summary>
        /// <response code="200">返回员工信息分页列表</response>
        /// <returns></returns>
        [HttpPost("[action]")]
        [ProducesResponseType(typeof(PageableList<AdminDto>), 200)]
        public IActionResult CheckAdminExists([FromBody]AdminCheckLoginNameDto requestDto)
        {
            return this.Ok(this.adminService.CheckAdminExists(requestDto.LoginName));
        }
        #endregion

        #region 创建员工
        /// <summary>
        /// 创建员工。
        /// </summary>
        /// <param name="dto">员工注册对象</param>
        /// <response code="201">已注册成功的用户信息。</response>
        /// <returns></returns>
        [HttpPost]
        [Log("添加员工账号")]
        [ProducesResponseType(typeof(AdminDto), 200)]
        public IActionResult CreateAdmin([FromBody]AdminRequestDto dto)
        {
            var ip = Request.Headers["X-Forwarded-For"].FirstOrDefault();
            if (string.IsNullOrEmpty(ip))
            {
                ip = HttpContext.Connection.RemoteIpAddress.ToString();
            }

            AdminDto result = this.adminService.Add(dto, ip);
            return this.Created(string.Format("/api/v1/sim/Admin/{0}", result.AdminId), result);
        }
        #endregion

        #region 获取员工列表
        /// <summary>
        /// 获取员工列表。
        /// </summary>
        /// <param name="companyId">公司Id</param>
        /// <param name="departmentId">部门Id</param>
        /// <param name="fullName">姓名</param>
        /// <param name="loginName">登录名</param>
        /// <param name="accountStatus">账号状态</param>
        /// <param name="sortName">排序字段</param>
        /// <param name="ascending">排序</param>
        /// <param name="index">当前页码</param>
        /// <param name="size">每页数据条数</param>
        /// <response code="200">返回员工信息分页列表</response>
        /// <returns></returns>
        [HttpGet]
        [ProducesResponseType(typeof(PageableList<AdminDto>), 200)]
        public IActionResult Get(
            [FromQuery(Name = "company_id")]int? companyId,
            [FromQuery(Name = "department_id")]int? departmentId,
            [FromQuery(Name = "login_name")]string loginName,
            [FromQuery(Name = "full_name")]string fullName,
            [FromQuery(Name = "account_status")]AccountStatus? accountStatus,
            [FromQuery(Name = "sort_name")]string sortName,
            [FromQuery(Name = "ascending")]bool? ascending,
            [FromQuery(Name = "index")]int index = 1,
            [FromQuery(Name = "size")]int size = 10)
        {
            return this.Ok(this.adminService.GetAdmins(companyId, departmentId, loginName, fullName, accountStatus, sortName, ascending, index, size));
        }
        #endregion

        #region 获取公司负责人配置员工列表
        /// <summary>
        /// 获取公司负责人配置员工列表。
        /// </summary>
        /// <response code="200">返回员工信息分页列表</response>
        /// <returns></returns>
        [HttpGet("[action]")]
        [ProducesResponseType(typeof(PageableList<AdminDto>), 200)]
        public IActionResult CompanyAdmins()
        {
            return this.Ok(this.adminService.GetAdminsForCompany());
        }
        #endregion

        #region 获取公司负责人配置员工列表
        /// <summary>
        /// 获取公司负责人配置员工列表。
        /// </summary>
        /// <response code="200">返回员工信息分页列表</response>
        /// <returns></returns>
        [HttpGet("[action]")]
        [ProducesResponseType(typeof(PageableList<AdminDto>), 200)]
        public IActionResult CurrentCompanyAdmins()
        {
            return this.Ok(this.adminService.GetCompanyAdminsAsync(this.Admin.CompanyId));
        }
        #endregion
        

        #region 登录
        /// <summary>
        /// 登录。
        /// </summary>
        /// <param name="dto">登录请求模型</param>
        /// <response code="200"></response>
        /// <returns></returns>
        [HttpPost("[action]")]
        [ProducesResponseType(typeof(TokenDto), 200)]
        [AllowAnonymous]
        public IActionResult Logon([FromBody]AdminLogonRequestDto dto)
        {
            var ip = Request.Headers["X-Forwarded-For"].FirstOrDefault();
            if (string.IsNullOrEmpty(ip))
            {
                ip = HttpContext.Connection.RemoteIpAddress.ToString();
            }

            var admin = this.adminService.Logon(dto.UserName, dto.Password, ip);

            if (admin == null)
            {
                throw new ArgumentException("用户名或密码不正确。");
            }
            return Ok(new TokenDto
            {
                Description = dto.UserName,
                AccessToken = admin.GenerateToken(expiration),
                ExpiresIn = (int)expiration.TotalSeconds,
                EndTime = DateTime.Now.AddSeconds((expiration.TotalSeconds - 12 * 3600))
            });
        }
        #endregion

        #region 微信登录
        /// <summary>
        /// 微信登录。
        /// </summary>
        /// <param name="dto">登录请求模型</param>
        /// <response code="200"></response>
        /// <returns></returns>
        [HttpPost("[action]")]
        [ProducesResponseType(typeof(TokenDto), 200)]
        [AllowAnonymous]
        public IActionResult WeChatLogon([FromBody]WechatUserLogonRequestDto dto)
        {
            var ip = Request.Headers["X-Forwarded-For"].FirstOrDefault();
            if (string.IsNullOrEmpty(ip))
            {
                ip = HttpContext.Connection.RemoteIpAddress.ToString();
            }
            var weChatUserInfoDto = this.weChatLoginService.GetUserInfo(dto.AccessToken, dto.UnionId);

            var adminAuthDto = this.adminAuthService.Get(AuthType.WeChat, weChatUserInfoDto.Unionid);
            if (adminAuthDto == null)
            {
                throw new ArgumentException("未完成授权绑定账户，无法登录!");
            }
            var admin = this.adminService.GetNonePasswordAdminInfoByAdminId(adminAuthDto.AdminId,null);
            if(admin.AccountStatus != AccountStatus.Using)
            {
                throw new ArgumentException("此账号已无权登录!");
            }
            if (admin == null)
            {
                throw new ArgumentException("用户名或密码不正确。");
            }
            return Ok(new TokenDto
            {
                Description = admin.LoginName,
                AccessToken = admin.GenerateToken(expiration),
                ExpiresIn = (int)expiration.TotalSeconds,
                EndTime = DateTime.Now.AddSeconds((expiration.TotalSeconds - 12 * 3600))
            });
        }
        #endregion

        #region 绑定微信登录(未登录)
        /// <summary>
        /// 绑定微信登录(未登录)
        /// </summary>
        /// <param name="dto">登录请求模型</param>
        /// <response code="200"></response>
        /// <returns></returns>
        [HttpPost("[action]")]
        [ProducesResponseType(typeof(TokenDto), 200)]
        [AllowAnonymous]
        public IActionResult BindingWeChat([FromBody]AdminBindWechatRequestDto dto)
        {
            var ip = Request.Headers["X-Forwarded-For"].FirstOrDefault();
            if (string.IsNullOrEmpty(ip))
            {
                ip = HttpContext.Connection.RemoteIpAddress.ToString();
            }
            var admin = this.adminService.Logon(dto.UserName, dto.Password, ip);

            if (admin == null)
            {
                throw new ArgumentException("用户名或密码不正确。");
            }
            var adminAuthList = this.adminAuthService.GetList(admin.AdminId);
            if(adminAuthList.Any(p=>p.AuthType == AuthType.WeChat))
            {
                throw new ArgumentException("此账号已绑定微信账号，无法绑定多个微信账号，请先解绑!");
            }
            AdminAuthDto authDto = this.adminAuthService.Add(new AdminAuthRequestDto()
            {
                AdminId = admin.AdminId,
                AuthType = AuthType.WeChat,
                AuthInfo = dto.AuthInfo,
                UnionId = dto.UnionId
            });
            if (authDto == null)
            {
                throw new ArgumentException("微信授权绑定失败!");
            }
            return Ok(new TokenDto
            {
                Description = dto.UserName,
                AccessToken = admin.GenerateToken(expiration),
                ExpiresIn = (int)expiration.TotalSeconds,
                EndTime = DateTime.Now.AddSeconds((expiration.TotalSeconds - 12 * 3600))
            });
        }
        #endregion

        #region 绑定微信登录(已登录)
        /// <summary>
        /// 绑定微信登录(已登录)
        /// </summary>
        /// <param name="dto">登录请求模型</param>
        /// <response code="200"></response>
        /// <returns></returns>
        [HttpPost("[action]")]
        [ProducesResponseType(typeof(NoContentResult), 204)]
        public IActionResult LogonBindingWeChat([FromBody]LogonBindWechatRequestDto dto)
        {
            var ip = Request.Headers["X-Forwarded-For"].FirstOrDefault();
            if (string.IsNullOrEmpty(ip))
            {
                ip = HttpContext.Connection.RemoteIpAddress.ToString();
            }
            
            var adminAuthList = this.adminAuthService.GetList(this.Admin.AdminId);
            if (adminAuthList.Any(p => p.AuthType == AuthType.WeChat))
            {
                throw new ArgumentException("此账号已绑定微信账号，无法绑定多个微信账号，请先解绑!");
            }
            AdminAuthDto authDto = this.adminAuthService.Add(new AdminAuthRequestDto()
            {
                AdminId = this.Admin.AdminId,
                AuthType = AuthType.WeChat,
                AuthInfo = dto.AuthInfo,
                UnionId = dto.UnionId
            });
            if (authDto == null)
            {
                throw new ArgumentException("微信授权绑定失败!");
            }
            return NoContent();
        }
        #endregion

        //#region 刷新Token
        ///// <summary>
        ///// 刷新Token--用户端需每此检查Token是否已经过期，如果过期了。需要先调用此接口刷新Token
        ///// </summary>
        ///// <param name="dto">Token</param>
        ///// <response code="200"></response>
        ///// <returns></returns>
        //[HttpPost("[action]")]
        //[ProducesResponseType(typeof(TokenDto), 200)]
        //[AllowAnonymous]
        //public IActionResult RefreshToken([FromBody]TokenDto dto)
        //{
        //    DateTime time = DateTime.MinValue;
        //    DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1, 0, 0, 0, 0));

        //    IEnumerable<Claim> claims = TokenExtension.ResolveToken(dto.AccessToken, RoleType.Admin);
        //    string exp = claims.Single(p => p.Type.Equals("exp")).Value;
        //    time = startTime.AddSeconds(int.Parse(exp));

        //    if (DateTime.UtcNow > time)
        //    {

        //        string userIdStr = claims.Single(p => p.Type.Equals(ClaimTypes.Name)).Value.Substring(6);
        //        string role = claims.Single(p => p.Type.Equals(ClaimTypes.Role)).Value;
        //        if (!role.Equals(RoleType.Admin.ToString()))
        //        {
        //            throw new ArgumentException("Token不是有效的");
        //        }
        //        if (!long.TryParse(userIdStr, out long adminId))
        //        {
        //            throw new ArgumentException("不用不是有效的");
        //        }
        //        else
        //        {
        //            var admin = adminService.GetAdminInfoByAdminId(adminId);
        //            if (admin == null)
        //            {
        //                throw new ArgumentException("用户不是有效的");
        //            }
        //            return Ok(new TokenDto
        //            {
        //                Description = dto.Description,
        //                AccessToken = admin.GenerateToken(expiration, RoleType.Admin),
        //                ExpiresIn = (int)expiration.TotalSeconds,
        //                EndTime = DateTime.Now.AddSeconds((expiration.TotalSeconds - 12 * 3600))
        //            });
        //        }

        //    }
        //    else
        //    {
        //        return Ok(dto);
        //    }
        //}
        //#endregion

        #region 修改员工账号信息
        /// <summary>
        /// 修改员工账号信息。
        /// </summary>
        /// <param name="dto">员工修改信息</param>
        /// <response code="200">修改是否成功</response>
        /// <returns></returns>
        [HttpPut]
        [Log("修改员工账号信息")]
        [ProducesResponseType(typeof(bool), 200)]
        public IActionResult Update([FromBody]AdminPutDto dto)
        {
            return this.Ok(this.adminService.Update(dto));
        }
        #endregion

        #region 员工修改自身信息
        /// <summary>
        /// 员工修改自身信息。
        /// </summary>
        /// <param name="dto">员工修改自身信息</param>
        /// <response code="200">修改是否成功</response>
        /// <returns></returns>
        [HttpPut("[action]")]
        [Log("员工修改自己账号信息")]
        [ProducesResponseType(typeof(bool), 200)]
        public IActionResult UpdateCurrentInfo([FromBody]AdminCurrentPutDto dto)
        {
            return this.Ok(this.adminService.UpdateSelfPassword(this.Admin.AdminId, dto));
        }
        #endregion

        #region 获取员工信息
        /// <summary>
        /// 获取员工信息。
        /// </summary>
        /// <response code="200">返回当前登录员工信息</response>
        /// <returns></returns>
        [HttpGet("[action]")]
        [ProducesResponseType(typeof(AdminDto), 200)]
        public IActionResult Current()
        {
            return this.Ok(this.Admin);
        }
        #endregion

        #region 获取员工角色列表
        /// <summary>
        /// 获取员工角色列表。
        /// </summary>
        /// <response code="200">返回员工角色列表</response>
        /// <returns></returns>
        [HttpGet("[action]")]
        [ProducesResponseType(typeof(IEnumerable<StaffViewDto>), 200)]
        public IActionResult StaffRoleList()
        {
            return this.Ok(this.StaffRoleRecord);
        }
        #endregion

        #region 获取联系人信息
        /// <summary>
        /// 获取联系人信息。
        /// </summary>
        /// <param name="adminId">联系人Id</param>
        /// <param name="isDepartmentPrincipal">是否是部门负责人查询</param>
        /// <response code="200">获取联系人信息</response>
        /// <returns></returns>
        [HttpGet("[action]/{id}")]
        [ProducesResponseType(typeof(AdminDto), 200)]
        public IActionResult ContactInfo([FromRoute(Name = "id")]long adminId,[FromQuery(Name = "is_department_principal")]bool? isDepartmentPrincipal)
        {
            if (isDepartmentPrincipal.HasValue&& isDepartmentPrincipal.Value)
            {
                return this.Ok(this.adminService.GetNonePasswordAdminInfoByAdminId(adminId,this.Admin));
            }
            else
            {
                return this.Ok(this.adminService.GetNonePasswordAdminInfoByAdminId(adminId));
            }
        }
        #endregion

        #region 设置登录系统角色
        /// <summary>
        /// 设置登录系统角色。
        /// </summary>
        /// <param name="staffOrganizationMappingRecordId">员工组织映射记录Id</param>
        /// <response code="204">设置登录系统角色完成</response>
        /// <returns></returns>
        [HttpPut("[action]/{id}")]
        [ProducesResponseType(typeof(NoContentResult), 204)]
        public IActionResult RoleActive([FromRoute(Name = "id")]long staffOrganizationMappingRecordId)
        {
            base.SetRoleActive(staffOrganizationMappingRecordId);
            return this.NoContent();
        }
        #endregion


        #region 停止员工账号
        /// <summary>
        /// 停止员工账号。
        /// </summary>
        /// <response code="204"></response>
        /// <returns></returns>
        [HttpPut("[action]/{admin_id}")]
        [Log("停止员工账号")]
        [ProducesResponseType(typeof(AdminDto), 200)]
        public IActionResult StopAdmin([FromRoute(Name = "admin_id")]long adminId)
        {
            return this.Ok(this.adminService.SetAdminAccountStatus(adminId, AccountStatus.Stop));
        }
        #endregion

        #region 重新开启员工账号
        /// <summary>
        /// 重新开启员工账号。
        /// </summary>
        /// <response code="204"></response>
        /// <returns></returns>
        [HttpPut("[action]/{admin_id}")]
        [Log("重新开启员工账号")]
        [ProducesResponseType(typeof(AdminDto), 200)]
        public IActionResult RestartAdmin([FromRoute(Name = "admin_id")]long adminId)
        {
            return this.Ok(this.adminService.SetAdminAccountStatus(adminId, AccountStatus.Using));
        }
        #endregion

        #region 删除员工信息
        /// <summary>
        /// 删除员工信息。
        /// </summary>
        /// <response code="204"></response>
        /// <returns></returns>
        [HttpPut("[action]/{admin_id}")]
        [Log("删除员工信息")]
        [ProducesResponseType(typeof(AdminDto), 200)]
        public IActionResult DeleteAdmin([FromRoute(Name = "admin_id")]long adminId)
        {
            return this.Ok(this.adminService.SetAdminAccountStatus(adminId, AccountStatus.Deleted));
        }
        #endregion

    }
}
